package com.xuexiang.xui_lib.component.guidview;

import ohos.agp.animation.Animator;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.ComponentTreeObserver;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.StackLayout;
import ohos.agp.components.Text;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.AbilityContext;
import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import ohos.global.icu.text.UnicodeSet;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.global.resource.solidxml.Pattern;
import ohos.global.resource.solidxml.TypedAttribute;

import com.xuexiang.xui_lib.ResourceTable;

import java.io.IOException;
import java.util.HashMap;

/**
 * @author xuexiang
 * @since 2018/11/29 上午12:47
 */
public class GuideCaseView extends StackLayout implements ComponentTreeObserver.GlobalLayoutListener {
    GuideCaseView(Context context) {
        super(context);
    }

    GuideCaseView(Context context, AttrSet attrs) {
        super(context, attrs);
    }

    GuideCaseView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    // Tag for container view
    private static final String CONTAINER_TAG = "ShowCaseViewTag";
    // SharedPreferences name
    private static final String PREF_NAME = "PrefShowCaseView";

    /**
     * 设置已经显示
     *
     * @param context
     * @param id
     */
    public static void setShowOnce(Context context, String id) {
        Preferences sharedPrefs = new DatabaseHelper(context).getPreferences(PREF_NAME);
        sharedPrefs.putBoolean(id, true).flush();
    }

    /**
     * 是否已显示
     *
     * @param context
     * @param id
     * @return boolean
     */
    public static boolean isShowOnce(Context context, String id) {
        Preferences sharedPrefs = new DatabaseHelper(context).getPreferences(PREF_NAME);
        return sharedPrefs.getBoolean(id, false);
    }

    /**
     * Resets the show once flag
     *
     * @param context context that should be used to create the shared preference instance
     * @param id id of the show once flag that should be reset
     */
    public static void resetShowOnce(Context context, String id) {
        Preferences sharedPrefs = new DatabaseHelper(context).getPreferences(PREF_NAME);
        sharedPrefs.delete(id).flush();
    }

    /**
     * Resets all show once flags
     *
     * @param context context that should be used to create the shared preference instance
     */
    public static void resetAllShowOnce(Context context) {
        Preferences sharedPrefs = new DatabaseHelper(context).getPreferences(PREF_NAME);
        sharedPrefs.clear().flush();
    }

    /**
     * Builder parameters
     */
    private AbilityContext mActivity;
    private String mTitle;
    //private UnicodeSet.SpanCondition mSpannedTitle;
    private String mId;
    private double mFocusCircleRadiusFactor;
    private Component mView;
    private Color mBackgroundColor;
    private Color mFocusBorderColor;
    private int mTitleGravity;
    private int mTitleStyle;
    private int mTitleSize;
    private Text.TextSizeType mTitleSizeUnit;
    private int mPictureResId;
    private int mPictureWidth;
    private int mPictureHeight;
    private int mPictureGravity;
    private int mPictureOffsetX;
    private int mPictureOffsetY;
    private int mCustomViewRes;
    private int mFocusBorderSize;
    private int mRoundRectRadius;
    private OnViewInflateListener mViewInflateListener;
    private Animator mEnterAnimation, mExitAnimation;
    private boolean mCloseOnTouch;
    private boolean mFitSystemWindows;
    private int mAdjustHeight;
    private int mFocusOffsetX;
    private FocusShape mFocusShape;
    private DismissListener mDismissListener;

    //private int mAnimationDuration = 400;
    private int mFocusAnimationMaxValue;
    private int mFocusAnimationStep;
    //private int mCenterX, mCenterY;
    private ComponentContainer mRoot;
    private Preferences mSharedPreferences;
    private Calculator mCalculator;

    private int mFocusPositionX, mFocusPositionY, mFocusCircleRadius, mFocusRectangleWidth, mFocusRectangleHeight;

    private boolean mFocusAnimationEnabled;

    public GuideCaseView(Builder builder) {
        this(builder.mActivity, builder.mView, builder.mId, builder.mTitle, builder.mSpannedTitle, builder.mTitleGravity, builder.mTitleStyle, builder.mTitleSize, builder.mTitleSizeUnit,
            builder.mFocusCircleRadiusFactor, builder.mBackgroundColor, builder.mFocusBorderColor, builder.mFocusBorderSize, builder.mCustomViewRes, builder.mViewInflateListener,
            builder.mEnterAnimation, builder.mExitAnimation, builder.mCloseOnTouch, builder.mFitSystemWindows, builder.mAdjustHeight, builder.mFocusOffSetX, builder.mFocusShape, builder.mDismissListener, builder.mRoundRectRadius,
            builder.mPictureResId, builder.mPictureWidth, builder.mPictureHeight, builder.mPictureGravity, builder.mPictureOffSetX, builder.mPictureOffSetY, builder.mFocusPositionX, builder.mFocusPositionY, builder.mFocusCircleRadius, builder.mFocusRectangleWidth,
            builder.mFocusRectangleHeight, builder.mFocusAnimationEnabled, builder.mFocusAnimationMaxValue, builder.mFocusAnimationStep);
        mRoot = builder.mAbilityRoot;
    }

    /**
     * Constructor for GuideCaseView
     *
     * @param activity Activity to show GuideCaseView in
     * @param view view to focus
     * @param id unique identifier for GuideCaseView
     * @param title title text
     * @param spannedTitle title text if spanned text should be used
     * @param titleGravity title gravity
     * @param titleStyle title text style
     * @param titleSize title text size
     * @param titleSizeUnit title text size unit
     * @param focusCircleRadiusFactor focus circle radius factor (default value = 1)
     * @param backgroundColor background color of GuideCaseView
     * @param focusBorderColor focus border color of GuideCaseView
     * @param focusBorderSize focus border size of GuideCaseView
     * @param customViewRes custom view layout resource
     * @param viewInflateListener inflate listener for custom view
     * @param enterAnimation enter animation for GuideCaseView
     * @param exitAnimation exit animation for GuideCaseView
     * @param closeOnTouch closes on touch if enabled
     * @param fitSystemWindows should be the same value of root view's fitSystemWindows value
     * @param focusShape shape of focus, can be circle or rounded rectangle
     * @param dismissListener listener that gets notified when showcase is dismissed
     * @param roundRectRadius round rectangle radius
     * @param focusPositionX focus at specific position X coordinate
     * @param focusPositionY focus at specific position Y coordinate
     * @param focusCircleRadius focus at specific position circle radius
     * @param focusRectangleWidth focus at specific position rectangle width
     * @param focusRectangleHeight focus at specific position rectangle height
     * @param animationEnabled flag to enable/disable animation
     */
    private GuideCaseView(AbilityContext activity, Component view, String id, String title, UnicodeSet.SpanCondition spannedTitle,
                          int titleGravity, int titleStyle, int titleSize, Text.TextSizeType titleSizeUnit, double focusCircleRadiusFactor,
                          Color backgroundColor, Color focusBorderColor, int focusBorderSize, int customViewRes,
                          OnViewInflateListener viewInflateListener, Animator enterAnimation,
                          Animator exitAnimation, boolean closeOnTouch, boolean fitSystemWindows, int adjustHeight, int focusOffsetX,
                          FocusShape focusShape, DismissListener dismissListener, int roundRectRadius, int pictureResId, int pictureWidth, int pictureHeight, int pictureGravity, int pictureOffsetX, int pictureOffsetY,
                          int focusPositionX, int focusPositionY, int focusCircleRadius, int focusRectangleWidth, int focusRectangleHeight,
                          final boolean animationEnabled, int focusAnimationMaxValue, int focusAnimationStep) {
        super(activity);
        mId = id;
        mActivity = activity;
        mView = view;
        mTitle = title;
        //mSpannedTitle = spannedTitle;
        mFocusCircleRadiusFactor = focusCircleRadiusFactor;
        mBackgroundColor = backgroundColor;
        mFocusBorderColor = focusBorderColor;
        mFocusBorderSize = focusBorderSize;
        mTitleGravity = titleGravity;
        mTitleStyle = titleStyle;
        mTitleSize = titleSize;
        mTitleSizeUnit = titleSizeUnit;
        mRoundRectRadius = roundRectRadius;
        mPictureResId = pictureResId;
        mPictureWidth = pictureWidth;
        mPictureHeight = pictureHeight;
        mPictureGravity = pictureGravity;
        mPictureOffsetX = pictureOffsetX;
        mPictureOffsetY = pictureOffsetY;
        mCustomViewRes = customViewRes;
        mViewInflateListener = viewInflateListener;
        mEnterAnimation = enterAnimation;
        mExitAnimation = exitAnimation;
        mCloseOnTouch = closeOnTouch;
        mFitSystemWindows = fitSystemWindows;
        mAdjustHeight = adjustHeight;
        mFocusOffsetX = focusOffsetX;
        mFocusShape = focusShape;
        mDismissListener = dismissListener;
        mFocusPositionX = focusPositionX;
        mFocusPositionY = focusPositionY;
        mFocusCircleRadius = focusCircleRadius;
        mFocusRectangleWidth = focusRectangleWidth;
        mFocusRectangleHeight = focusRectangleHeight;
        mFocusAnimationEnabled = animationEnabled;
        mFocusAnimationMaxValue = focusAnimationMaxValue;
        mFocusAnimationStep = focusAnimationStep;

        initializeParameters();
    }

    /**
     * Calculates and set initial parameters
     */
    private void initializeParameters() {
        mBackgroundColor = mBackgroundColor != null ? mBackgroundColor :
            new Color(mContext.getColor(ResourceTable.Color_default_guide_case_view_background_color));
        mTitleGravity = mTitleGravity >= 0 ? mTitleGravity : TextAlignment.CENTER;
        mTitleStyle = mTitleStyle != 0 ? mTitleStyle : ResourceTable.Pattern_DefaultGuideCaseTitleStyle;

//        Display display = DisplayManager.getInstance().getDefaultDisplay(mActivity).get();
        //int deviceWidth = display.getAttributes().width;
        //int deviceHeight = display.getAttributes().height;
        //mCenterX = deviceWidth / 2;
        //mCenterY = deviceHeight / 2;
        mSharedPreferences = new DatabaseHelper(mActivity).getPreferences(PREF_NAME);
    }

    /**
     * Shows GuideCaseView
     */
    public void show() {
        if (mActivity == null || (mId != null && isShownBefore())) {
            if (mDismissListener != null) {
                mDismissListener.onSkipped(mId);
            }
            return;
        }

        if (mView != null) {
            // if view is not laid out get width/height values in onGlobalLayout
            if (mView.getWidth() == 0 && mView.getHeight() == 0) {
                mView.getComponentTreeObserver().addTreeLayoutChangedListener(this);
            } else {
                focus();
            }
        } else {
            focus();
        }
    }

    private void focus() {
        mCalculator = new Calculator(mActivity, mFocusShape, mView, mFocusCircleRadiusFactor,
            mFitSystemWindows, mAdjustHeight, mFocusOffsetX);

//        mRoot = getAbilityContent();
//        GuideCaseView visibleView = mRoot.findComponentById(CONTAINER_TAG);
//        GuideCaseView visibleView = new GuideCaseView(mActivity);
        setClickable(true);
//        if (visibleView == null) {
        setTag(CONTAINER_TAG);
        if (mCloseOnTouch) {
            setClickedListener(new ClickedListener() {
                @Override
                public void onClick(Component component) {
                    hide();
                }
            });
        }
        setLayoutConfig(new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
            ComponentContainer.LayoutConfig.MATCH_PARENT));
        mRoot.addComponent(this);


        GuideImageView imageView = new GuideImageView(mActivity);
        imageView.setFocusAnimationParameters(mFocusAnimationMaxValue, mFocusAnimationStep);
        if (mCalculator.hasFocus()) {
            //mCenterX = mCalculator.getCircleCenterX();
            //mCenterY = mCalculator.getCircleCenterY();
        }

        imageView.setParameters(mBackgroundColor, mCalculator);
        if (mFocusRectangleWidth > 0 && mFocusRectangleHeight > 0) {
            mCalculator.setRectPosition(mFocusPositionX, mFocusPositionY, mFocusRectangleWidth, mFocusRectangleHeight);
        }
        if (mFocusCircleRadius > 0) {
            mCalculator.setCirclePosition(mFocusPositionX, mFocusPositionY, mFocusCircleRadius);
        }
        imageView.setAnimationEnabled(mFocusAnimationEnabled);
        imageView.setLayoutConfig(new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
            ComponentContainer.LayoutConfig.MATCH_PARENT));
        if (mFocusBorderColor != null && mFocusBorderSize > 0) {
            imageView.setBorderParameters(mFocusBorderColor, mFocusBorderSize);
        }
        if (mRoundRectRadius > 0) {
            imageView.setRoundRectRadius(mRoundRectRadius);
        }
        addComponent(imageView);

        if (mCustomViewRes == 0) {
            if (mPictureResId == 0) {
                inflateTitleView();
            } else {
                inflatePicture();
            }
        } else {
            inflateCustomView(mCustomViewRes, mViewInflateListener);
        }

        startEnterAnimation();
        writeShown();
//        }
    }

    private ComponentContainer getAbilityContent() {
        return mRoot;
    }

    /**
     * Check is GuideCaseView visible
     *
     * @param activity
     * @return Boolean
     */
    public static Boolean isVisible(AbilityContext activity) {
//        GuideCaseView mContainer = mRoot.findViewWithTag(CONTAINER_TAG);
//        return mContainer != null;
        return false;
    }

    /**
     * Hide  GuideCaseView
     *
     * @param activity should be used to hide GuideCaseView inside it
     */
    public static void hideCurrent(AbilityContext activity) {
//        GuideCaseView mContainer = mRoot.findViewWithTag(CONTAINER_TAG);
//        mContainer.hide();
    }

    /**
     * Starts enter animation of GuideCaseView
     */
    private void startEnterAnimation() {
        if (mEnterAnimation != null) {
            mEnterAnimation.start();
        } else if (Utils.shouldShowCircularAnimation()) {
            doCircularEnterAnimation();
        } else {
            this.setAlpha(0);
            this.createAnimatorProperty()
                .alpha(1)
                .setDuration(400)
                .start();
        }
    }

    /**
     * Hides GuideCaseView with animation
     */
    public void hide() {
        if (mExitAnimation != null) {
            mExitAnimation.start();
        } else if (Utils.shouldShowCircularAnimation()) {
            doCircularExitAnimation();
        } else {
            this.setAlpha(1);
            this.createAnimatorProperty()
                .alpha(0)
                .setDuration(400)
                .setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {

                    }

                    @Override
                    public void onStop(Animator animator) {

                    }

                    @Override
                    public void onCancel(Animator animator) {

                    }

                    @Override
                    public void onEnd(Animator animator) {
                        removeView();
                    }

                    @Override
                    public void onPause(Animator animator) {

                    }

                    @Override
                    public void onResume(Animator animator) {

                    }
                })
                .start();
        }
    }

    /**
     * Inflates custom view
     *
     * @param layout layout for custom view
     * @param viewInflateListener inflate listener for custom view
     */
    private void inflateCustomView(int layout, OnViewInflateListener viewInflateListener) {
        Component view = LayoutScatter.getInstance(mActivity).parse(layout, null, false);
        this.addComponent(view);
        if (viewInflateListener != null) {
            viewInflateListener.onViewInflated(view);
        }
    }

    /**
     * Inflates title view layout
     */
    private void inflateTitleView() {
        inflateCustomView(ResourceTable.Layout_gcv_layout_title, new OnViewInflateListener() {
            @Override
            public void onViewInflated(Component view) {
                Text textView = (Text) view.findComponentById(ResourceTable.Id_gcv_title);
                Pattern pattern = null;

                try {
                    pattern = getContext()
                        .getResourceManager()
                        .getElement(mTitleStyle)
                        .getPattern();
                    HashMap<String, TypedAttribute> hashMap = pattern.getPatternHash();
                    for (String name : hashMap.keySet()) {
                        TypedAttribute typedAttribute = hashMap.get(name);
                        if (name.equals("text_size")) {
                            textView.setTextSize((int) typedAttribute.getFloatValue());
                        } else if (name.equals("color")) {
                            textView.setTextColor(new Color(typedAttribute.getColorValue()));
                        } else if (name.equals("text_font")) {
                            textView.setFont(new Font.Builder(typedAttribute.getStringValue()).build());
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (NotExistException e) {
                    e.printStackTrace();
                } catch (WrongTypeException e) {
                    e.printStackTrace();
                }

                if (mTitleSize != -1) {
                    textView.setTextSize(mTitleSize, mTitleSizeUnit);
                }
                textView.setTextAlignment(mTitleGravity);
//                textView.setTypeface(XUI.getDefaultTypeface());
                textView.setText(mTitle);
            }
        });
    }

    /**
     * Inflates picture view layout
     */
    private void inflatePicture() {
        inflateCustomView(ResourceTable.Layout_gcv_layout_image, new OnViewInflateListener() {

            @Override
            public void onViewInflated(Component view) {
                Image imageView = (Image) findComponentById(ResourceTable.Id_gcv_img);
                imageView.setImageAndDecodeBounds(mPictureResId);
                LayoutConfig params = (LayoutConfig) imageView.getLayoutConfig();
                params.alignment = mPictureGravity;
                if (mPictureWidth != 0) {
                    params.width = mPictureWidth;
                }
                if (mPictureHeight != 0) {
                    params.height = mPictureHeight;
                }
                if (mPictureOffsetY > 0) {
                    params.setMarginTop(mPictureOffsetY);
                } else {
                    params.setMarginBottom(mPictureOffsetY);
                }
                if (mPictureOffsetX > 0) {
                    params.setMarginLeft(mPictureOffsetY);
                } else {
                    params.setMarginRight(mPictureOffsetX);
                }
                imageView.setLayoutConfig(params);
            }
        });
    }

    /**
     * Circular reveal enter animation
     */
    private void doCircularEnterAnimation() {
//        final int revealRadius = (int) Math.hypot(
//                getWidth(), getHeight());
//        int startRadius = 0;
//        if (mView != null) {
//            startRadius = mView.getWidth() / 2;
//        } else if (mFocusCircleRadius > 0 || mFocusRectangleWidth > 0 || mFocusRectangleHeight > 0) {
//            mCenterX = mFocusPositionX;
//            mCenterY = mFocusPositionY;
//        }
//        Animator enterAnimator = ViewAnimationUtils.createCircularReveal(GuideCaseView.this,
//                mCenterX, mCenterY, startRadius, revealRadius);
//        enterAnimator.setDuration(mAnimationDuration);
//        enterAnimator.setInterpolator(AnimationUtils.loadInterpolator(mActivity,
//        enterAnimator.start();
    }

    /**
     * Circular reveal exit animation
     */
    private void doCircularExitAnimation() {
//        final int revealRadius = (int) Math.hypot(getWidth(), getHeight());
//        Animator exitAnimator = ViewAnimationUtils.createCircularReveal(this,
//                mCenterX, mCenterY, revealRadius, 0f);
//        exitAnimator.setDuration(mAnimationDuration);
//        exitAnimator.setInterpolator(AnimationUtils.loadInterpolator(mActivity,
//        exitAnimator.addListener(new AnimatorListenerAdapter() {
//            @Override
//            public void onAnimationEnd(Animator animation) {
//                removeView();
//
//            }
//        });
//        exitAnimator.start();
    }

    /**
     * Saves the GuideCaseView id to SharedPreferences that is shown once
     */
    private void writeShown() {
        if (mId == null) {
            return;
        }
        mSharedPreferences.putBoolean(mId, true);
        mSharedPreferences.flush();
    }

    /**
     * Returns if GuideCaseView with given id is shown before
     *
     * @return true if show before
     */
    public boolean isShownBefore() {
        return mSharedPreferences.getBoolean(mId, false);
    }

    /**
     * Removes GuideCaseView view from activity root view
     */
    public void removeView() {
        mRoot.removeComponent(this);
        if (mDismissListener != null) {
            mDismissListener.onDismiss(mId);
        }
    }

    protected DismissListener getDismissListener() {
        return mDismissListener;
    }

    protected void setDismissListener(DismissListener dismissListener) {
        mDismissListener = dismissListener;
    }

    public int getFocusCenterX() {
        return mCalculator.getCircleCenterX();
    }

    public int getFocusCenterY() {
        return mCalculator.getCircleCenterY();
    }

    public float getFocusRadius() {
        return FocusShape.CIRCLE.equals(mFocusShape) ? mCalculator.circleRadius(0, 1) : 0;
    }

    public int getFocusWidth() {
        return mCalculator.getFocusWidth();
    }

    public int getFocusHeight() {
        return mCalculator.getFocusHeight();
    }

    @Override
    public void onGlobalLayoutUpdated() {
        mView.getComponentTreeObserver().removeTreeLayoutChangedListener(this);
        focus();
    }


    /**
     * Builder class for {@link GuideCaseView}
     */
    public static class Builder {
        private AbilityContext mActivity;
        private Component mView;
        private ComponentContainer mAbilityRoot;
        private String mId;
        private String mTitle;
        private UnicodeSet.SpanCondition mSpannedTitle;
        private double mFocusCircleRadiusFactor = 1;
        private Color mBackgroundColor;
        private Color mFocusBorderColor;
        private int mTitleGravity = -1;
        private int mTitleSize = -1;
        private Text.TextSizeType mTitleSizeUnit = Text.TextSizeType.PX;
        private int mTitleStyle;
        private int mPictureResId;
        private int mPictureWidth;
        private int mPictureHeight;
        private int mPictureGravity = LayoutAlignment.CENTER;
        private int mPictureOffSetX;
        private int mPictureOffSetY;
        private int mCustomViewRes;
        private int mRoundRectRadius;
        private OnViewInflateListener mViewInflateListener;
        private Animator mEnterAnimation, mExitAnimation;
        private boolean mCloseOnTouch = true;
        private boolean mFitSystemWindows;
        private int mAdjustHeight = -1;
        private int mFocusOffSetX;
        private FocusShape mFocusShape = FocusShape.CIRCLE;
        private DismissListener mDismissListener = null;
        private int mFocusBorderSize;
        private int mFocusPositionX, mFocusPositionY, mFocusCircleRadius, mFocusRectangleWidth, mFocusRectangleHeight;
        private boolean mFocusAnimationEnabled = true;
        private int mFocusAnimationMaxValue = 20;
        private int mFocusAnimationStep = 1;

        /**
         * Constructor for Builder class
         *
         * @param activity Activity to show GuideCaseView in
         */
        public Builder(AbilityContext activity) {
            mActivity = activity;
        }

        /**
         * 设置标题文字
         *
         * @param title title text
         * @return Builder
         */
        public Builder title(String title) {
            mTitle = title;
            mSpannedTitle = null;
            return this;
        }

        /**
         * title
         *
         * @param title title text
         * @return Builder
         */
        public Builder title(UnicodeSet.SpanCondition title) {
            mSpannedTitle = title;
            mTitle = null;
            return this;
        }

        /**
         * 设置图片资源
         *
         * @param pictureResId 图片资源Id
         * @return Builder
         */
        public Builder picture(int pictureResId) {
            mPictureResId = pictureResId;
            return this;
        }

        /**
         * picture
         *
         * @param pictureResId 图片资源Id
         * @param width 图片资源Id
         * @param height 图片资源Id
         * @return Builder
         */
        public Builder picture(int pictureResId, int width, int height) {
            mPictureResId = pictureResId;
            mPictureWidth = width;
            mPictureHeight = height;
            return this;
        }

        /**
         * pictureGravity
         *
         * @param pictureGravity picture gravity
         * @return Builder
         */
        public Builder pictureGravity(int pictureGravity) {
            mPictureGravity = pictureGravity;
            return this;
        }

        /**
         * pictureGravity
         *
         * @param pictureGravity
         * @param offsetX
         * @param offsetY
         * @return Builder
         */
        public Builder pictureGravity(int pictureGravity, int offsetX, int offsetY) {
            mPictureGravity = pictureGravity;
            mPictureOffSetX = offsetX;
            mPictureOffSetY = offsetY;
            return this;
        }

        /**
         * pictureOffSet
         *
         * @param offsetX
         * @param offsetY
         * @return Builder
         */
        public Builder pictureOffSet(int offsetX, int offsetY) {
            mPictureOffSetX = offsetX;
            mPictureOffSetY = offsetY;
            return this;
        }

        /**
         * pictureOffSetX
         *
         * @param offsetX
         * @return Builder
         */
        public Builder pictureOffSetX(int offsetX) {
            mPictureOffSetX = offsetX;
            return this;
        }

        /**
         * pictureOffSetY
         *
         * @param offsetY
         * @return Builder
         */
        public Builder pictureOffSetY(int offsetY) {
            mPictureOffSetY = offsetY;
            return this;
        }

        /**
         * titleStyle
         *
         * @param style title text style
         * @param titleGravity title TextAlignment
         * @return Builder
         */
        public Builder titleStyle(int style, int titleGravity) {
            mTitleGravity = titleGravity;
            mTitleStyle = style;
            return this;
        }

        /**
         * 设置聚焦边框的颜色
         *
         * @param focusBorderColor Border color for focus shape
         * @return Builder
         */
        public Builder focusBorderColor(Color focusBorderColor) {
            mFocusBorderColor = focusBorderColor;
            return this;
        }

        /**
         * 设置聚焦边框的粗细
         *
         * @param focusBorderSize Border size for focus shape
         * @return Builder
         */
        public Builder focusBorderSize(int focusBorderSize) {
            mFocusBorderSize = focusBorderSize;
            return this;
        }

        /**
         * titleGravity
         *
         * @param titleGravity title gravity
         * @return Builder
         */
        public Builder titleGravity(int titleGravity) {
            mTitleGravity = titleGravity;
            return this;
        }

        /**
         * the defined text size overrides any defined size in the default or provided style
         *
         * @param titleSize title size
         * @param unit title text unit
         * @return Builder
         */
        public Builder titleSize(int titleSize, Text.TextSizeType unit) {
            mTitleSize = titleSize;
            mTitleSizeUnit = unit;
            return this;
        }

        /**
         * showOnce
         *
         * @param id unique identifier for GuideCaseView
         * @return return
         */
        public Builder showOnce(String id) {
            mId = id;
            return this;
        }

        /**
         * 设置聚焦的控件
         *
         * @param view view to focus
         * @return Builder
         */
        public Builder focusOn(Component view) {
            mView = view;
            return this;
        }

        public Builder root(ComponentContainer view) {
            mAbilityRoot = view;
            return this;
        }

        /**
         * 设置引导朦层的背景颜色
         *
         * @param backgroundColor background color of GuideCaseView
         * @return Builder
         */
        public Builder backgroundColor(Color backgroundColor) {
            mBackgroundColor = backgroundColor;
            return this;
        }

        /**
         * focusCircleRadiusFactor
         *
         * @param focusCircleRadiusFactor focus circle radius factor (default value = 1)
         * @return Builder
         */
        public Builder focusCircleRadiusFactor(double focusCircleRadiusFactor) {
            mFocusCircleRadiusFactor = focusCircleRadiusFactor;
            return this;
        }

        /**
         * 设置自定义引导朦层布局
         *
         * @param layoutResource custom view layout resource
         * @param listener inflate listener for custom view
         * @return Builder
         */
        public Builder customView(int layoutResource, OnViewInflateListener listener) {
            mCustomViewRes = layoutResource;
            mViewInflateListener = listener;
            return this;
        }

        /**
         * 设置进入动画
         *
         * @param enterAnimation enter animation for GuideCaseView
         * @return Builder
         */
        public Builder enterAnimation(Animator enterAnimation) {
            mEnterAnimation = enterAnimation;
            return this;
        }

        /**
         * 设置退出动画
         *
         * @param exitAnimation exit animation for GuideCaseView
         * @return Builder
         */
        public Builder exitAnimation(Animator exitAnimation) {
            mExitAnimation = exitAnimation;
            return this;
        }

        /**
         * closeOnTouch
         *
         * @param closeOnTouch
         * @return Builder
         */
        public Builder closeOnTouch(boolean closeOnTouch) {
            mCloseOnTouch = closeOnTouch;
            return this;
        }

        /**
         * This should be the same as root view's fitSystemWindows value
         *
         * @param fitSystemWindows fitSystemWindows value
         * @return Builder
         */
        public Builder fitSystemWindows(boolean fitSystemWindows) {
            mFitSystemWindows = fitSystemWindows;
            return this;
        }

        /**
         * 自动适应屏幕高度
         *
         * @return Builder
         */
        public Builder fitWindowsAuto() {
            mFitSystemWindows = true;
//                adjustHeight(0);
            return this;
        }

        /**
         * 调整的高度
         *
         * @param adjustHeight
         * @return Builder
         */
        public Builder adjustHeight(int adjustHeight) {
            mAdjustHeight = adjustHeight;
            return this;
        }

        /**
         * 调整聚焦的X偏移
         *
         * @param offSetX
         * @return Builder
         */
        public Builder setFocusOffSetX(int offSetX) {
            mFocusOffSetX = offSetX;
            return this;
        }

        /**
         * 设置聚焦的形状，默认是圆形
         *
         * @param focusShape
         * @return Builder
         */
        public Builder focusShape(FocusShape focusShape) {
            mFocusShape = focusShape;
            return this;
        }

        /**
         * Focus round rectangle at specific position
         * 自定义聚焦的矩形区域
         *
         * @param positionX focus at specific position Y coordinate
         * @param positionY focus at specific position circle radius
         * @param positionWidth focus at specific position rectangle width
         * @param positionHeight focus at specific position rectangle height
         * @return Builder
         */

        public Builder focusRectAtPosition(int positionX, int positionY, int positionWidth, int positionHeight) {
            mFocusPositionX = positionX;
            mFocusPositionY = positionY;
            mFocusRectangleWidth = positionWidth;
            mFocusRectangleHeight = positionHeight;
            return this;
        }

        /**
         * Focus circle at specific position
         * 自定义聚焦的环形区域
         *
         * @param positionX focus at specific position Y coordinate
         * @param positionY focus at specific position circle radius
         * @param radius focus at specific position circle radius
         * @return Builder
         */

        public Builder focusCircleAtPosition(int positionX, int positionY, int radius) {
            mFocusPositionX = positionX;
            mFocusPositionY = positionY;
            mFocusCircleRadius = radius;
            return this;
        }

        /**
         * 设置引导朦层消失的监听
         *
         * @param dismissListener the dismiss listener
         * @return Builder
         */
        public Builder dismissListener(DismissListener dismissListener) {
            mDismissListener = dismissListener;
            return this;
        }

        public Builder roundRectRadius(int roundRectRadius) {
            mRoundRectRadius = roundRectRadius;
            return this;
        }

        /**
         * disable Focus Animation
         *
         * @return Builder
         */
        public Builder disableFocusAnimation() {
            mFocusAnimationEnabled = false;
            return this;
        }

        public Builder focusAnimationMaxValue(int focusAnimationMaxValue) {
            mFocusAnimationMaxValue = focusAnimationMaxValue;
            return this;
        }

        public Builder focusAnimationStep(int focusAnimationStep) {
            mFocusAnimationStep = focusAnimationStep;
            return this;
        }

        /**
         * builds the builder
         *
         * @return {@link GuideCaseView} with given parameters
         */
        public GuideCaseView build() {
            return new GuideCaseView(this);
        }

        /**
         * 显示
         */
        public void show() {
            build().show();
        }
    }
}
